<template>
  <div
    @mouseenter="hovering = true"
    @mouseleave="hovering = false"
    style="width: 100%"
  >
    <el-input
      v-if="inputDisabled || disabled"
      disabled
      v-model="message"
    />
    <el-input
      v-else
      ref="messageRef"
      v-model="message"
      :placeholder="placeholder"
      :size="size"
      @click="messageClick"
      @input="messageChange"
    >
      <template #suffix>
        <cc-icon
          v-if="hovering"
          style="cursor: pointer;color: #c0c4cc"
          @click.stop="clearInput"
          iconId="018dca412c4ebd53fd1d"
        />
      </template>
    </el-input>
    <el-popover
      ref="popoverRef"
      :width="popoverWidth"
      placement="bottom-start"
      :fallback-placements="['bottom', 'right', 'left', 'top']"
      :visible-arrow="true"
      :visible="popoverVisible"
      popper-class="popper-box"
      trigger="click"
      :virtual-ref="messageRef"
      virtual-triggering
    >
      <el-scrollbar
        wrap-class="popover-scrollbar"
        wrap-style="min-height:0px;max-height: 400px;"
        view-style="height:100%;"
        v-click-outside="clickOutside"
        v-loading="loading"
        element-loading-text="数据加载中..."
        :noresize="false"
      >
        <el-row class="tree-row">
          <el-tree
            style="width: 100%"
            ref="tree"
            node-key="id"
            :data="treeData"
            :props="treeProps"
            :highlight-current="true"
            :default-expanded-keys="expandedData"
            :filter-node-method="filterNode"
            :expand-on-click-node="true"
            @node-expand="nodeExpand"
            @node-click="nodeClick"
          ></el-tree>
        </el-row>
      </el-scrollbar>
    </el-popover>
  </div>
</template>

<script setup>
import { ref, watch, onMounted, nextTick } from 'vue';
import { useDisabled, ClickOutside as vClickOutside } from 'element-plus';
import { getEmployee } from '@/utils/system';

const emit = defineEmits(['update:modelValue', 'change', 'update:name']);
const props = defineProps({
  modelValue: {
    type: String,
    default: ''
  },
  placeholder: {
    type: String,
    default: '--请选择--'
  },
  size: {
    type: String,
    default: 'default'
  },
  disabled: {
    type: Boolean,
    default: false
  }
});

const initializing = ref(false);
const tree = ref();
const popoverRef = ref();
const popoverWidth = ref('-');
const popoverVisible = ref(false);
const messageRef = ref();
const message = ref('');
const loading = ref(false);
const selectedId = ref('');
const expandedData = ref([]);
const inputDisabled = useDisabled();
const treeData = ref([]);
const treeProps = ref({
  children: 'children',
  isLeaf: 'leaf',
  label: 'text'
});
const hovering = ref(false);

const clearInput = () => {
  changeValue('', '');
};

const messageClick = () => {
  popoverVisible.value = true;
  message.value = '';
  tree.value.filter('');
  const width = messageRef.value.$el.getBoundingClientRect().width;
  if (width && width > 0) {
    popoverWidth.value = width;
  }
  return false;
};

const messageChange = () => {
  tree.value.filter(message.value);
};

const clickOutside = () => {
  popoverVisible.value = false;
};

const changeValue = (id, value) => {
  initializing.value = true;
  tree.value.setChecked(id);
  selectedId.value = id;
  message.value = value;
  emit("update:modelValue", id || '');
  emit("change");

  nextTick(() => {
    popoverVisible.value = false;
    initializing.value = false;
  });
};

const filterNode = (value, data) => {
  if (!value) return true;
  return data.text.indexOf(value) >= 0;
};

const nodeExpand = () => {
  setTimeout(() => {
    popoverRef.value && popoverRef.value.popperRef.popperInstanceRef.forceUpdate();
  }, 300);
};

const nodeClick = (data) => {
  if (data.disabled === true) return;
  changeValue(data.id || '', data.text || '');
};

const loadTree = async () => {
  treeData.value = await getEmployee();
  if (treeData.value && treeData.value.length === 1) {
    expandedData.value = [treeData.value[0].id];
  }
  calcValue();
};

const calcValue = () => {
  if (treeData.value == null || treeData.value.length <= 0) {
    message.value = selectedId.value;
  } else {
    const list = findData(treeData.value, (selectedId.value || '').split(','));
    if (list && list.length > 0) {
      for (let i = 0; i < list.length; i++) {
        message.value = list[i].text;
      }
    } else {
      message.value = '';
    }
  }
};

const findData = (list, ids) => {
  let results = [];
  if (list === undefined || list == null || ids === undefined || ids == null) {
    return results;
  }

  for (let i = 0; i < list.length; i++) {
    let id = list[i].id + '';
    if (id !== '0' && ids.indexOf(id) >= 0) {
      results.push(list[i]);
    }

    if (list[i].children !== undefined && list[i].children != null) {
      results = results.concat(findData(list[i].children, ids));
    }
  }

  return results;
};

watch(() => props.modelValue, (newVal) => {
  if (initializing.value) return;

  selectedId.value = newVal || '';
  calcValue();
});

onMounted(() => {
  selectedId.value = props.modelValue || '';
  loadTree();
});
</script>

<style scoped lang="scss">
.popper-box {
  .node-item {
    display: flex;
    flex-direction: row;
    align-items: center;
    width: 100%;

    .node-label {
      flex-grow: 1;
      width: 1px;
      text-overflow: ellipsis;
      overflow: hidden;
      display: flex;

      > span {
        width: 100%;
        text-overflow: ellipsis;
        overflow: hidden;
      }
    }
  }
}
</style>